package com.luoye.audiodemo.weight

import android.content.Context
import android.graphics.BitmapFactory
import android.opengl.GLES20
import android.opengl.GLSurfaceView
import android.opengl.GLUtils
import android.util.AttributeSet
import com.luoye.audiodemo.R
import com.luoye.audiodemo.egl.YShaderUtil
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import java.nio.ShortBuffer
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

/**
 * 绘制一个 bitmap
 */
class MyGLBitmapView2 @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
) : GLSurfaceView(context, attrs) {
    init {
        setEGLContextClientVersion(2)
        setRenderer(MyGLViewRenderer(context))
        // 设置绘制模式。
        renderMode = RENDERMODE_WHEN_DIRTY
    }
    class MyGLViewRenderer(var context: Context): Renderer {

        val bitmap = BitmapFactory.decodeResource(context.resources, R.drawable.wbb)

        var  triangle:Triangle?=null
        var glTextureId:Int?=null
        override fun onSurfaceCreated(p0: GL10?, p1: EGLConfig?) {
            glTextureId = OpenGLUtils.createTexture(bitmap, GLES20.GL_NEAREST, GLES20.GL_LINEAR,
                GLES20.GL_CLAMP_TO_EDGE, GLES20.GL_CLAMP_TO_EDGE)

            triangle=Triangle(context)
        }

        override fun onSurfaceChanged(p0: GL10?, w: Int, h: Int) {
            GLES20.glViewport(0, 0, w, h)
        }

        override fun onDrawFrame(p0: GL10?) {
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
            GLES20.glClearColor(1f, 0f, 0f, 1f)
            triangle?.draw()
        }
    }
    class Triangle(var mContext: Context) {

        // 顶点坐标。
        val vertexBuffer: FloatBuffer by lazy {
            //顶点坐标
            val vertexData = floatArrayOf(
                -1f, -1f,
                1f, -1f,
                -1f, 1f,
                1f, 1f

            )
            val buffer = ByteBuffer.allocateDirect(vertexData.size * 4).order(ByteOrder.nativeOrder())
                .asFloatBuffer().put(vertexData)
            buffer.position(0)
            buffer
        }

        // 纹理的buffer
        val fragmentBuffer: FloatBuffer by lazy {
            //顶点坐标
            val vertexData = floatArrayOf(
                0f, 1f,
                1f, 1f,
                0f, 0f,
                1f, 0f
            )
            val buffer = ByteBuffer.allocateDirect(vertexData.size * 4).order(ByteOrder.nativeOrder())
                .asFloatBuffer().put(vertexData)
            buffer.position(0)
            buffer
        }


        //加载顶点着色器 shader
        val vertexSource = "attribute vec4 vPosition;\n" +
                "attribute vec2 fPosition;\n" +
                "varying vec2 ft_Position;\n" +
                "\n" +
                "void main(){\n" +
                "    gl_Position = vPosition;\n" +
                "    ft_Position = fPosition;\n" +
                "}"
        //加载片元着色器 shader
        val fragmentSource ="precision mediump float;\n" +
                "varying vec2 ft_Position;\n" +
                "uniform sampler2D vTexture;\n" +
                "\n" +
                "void main(){\n" +
                "    gl_FragColor = texture2D(vTexture, ft_Position);\n" +
                "}"

        /**
         * 着色器程序ID引用
         */
        private var mProgram: Int
        var vPosition: Int? = null
        var fPosition: Int? = null
        var textureIds = IntArray(1)
        init {
            // 编译顶点着色器和片段着色器

            val vertexShader: Int = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource)
            val fragmentShader: Int = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource)
            // glCreateProgram函数创建一个着色器程序，并返回新创建程序对象的ID引用
            mProgram = GLES20.glCreateProgram().also {
                // 把顶点着色器添加到程序对象
                GLES20.glAttachShader(it, vertexShader)
                // 把片段着色器添加到程序对象
                GLES20.glAttachShader(it, fragmentShader)
                // 连接并创建一个可执行的OpenGL ES程序对象
                GLES20.glLinkProgram(it)
            }
            //从渲染程序中得到着顶点色器中的属性
            vPosition = GLES20.glGetAttribLocation(mProgram, "vPosition")
            //从渲染程序中得到片元着色器中的属性
            fPosition = GLES20.glGetAttribLocation(mProgram, "fPosition")
            //创建 1个纹理,放入到 int [] textureIds, 一共有 30多个 纹理
            GLES20.glGenTextures(1, textureIds, 0) //第三个参数是指从哪儿开始取
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds.get(0))
            //设置纹理的环绕方式
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT)
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT)
            //设置纹理的过滤方式
            GLES20.glTexParameteri(
                GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_MIN_FILTER,
                GLES20.GL_LINEAR
            )
            GLES20.glTexParameteri(
                GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_MAG_FILTER,
                GLES20.GL_LINEAR
            )
            //解绑纹理 指的是离开对 纹理的配置，进入下一个状态
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0)

        }

        private fun loadShader(type: Int, shaderCode: String): Int {
            // glCreateShader函数创建一个顶点着色器或者片段着色器,并返回新创建着色器的ID引用
            val shader = GLES20.glCreateShader(type)
            // 把着色器和代码关联,然后编译着色器
            GLES20.glShaderSource(shader, shaderCode)
            GLES20.glCompileShader(shader)
            return shader
        }
        fun draw() {
            //清除屏幕，此处用的是红色
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
            GLES20.glClearColor(1f, 0f, 0f, 1f)
          //使用着色器源程序
            GLES20.glUseProgram(mProgram)
           //使能顶点属性数组，使之有效
            GLES20.glEnableVertexAttribArray(vPosition!!)
            //使能之后，为顶点属性赋值，绑定顶点坐标
            GLES20.glVertexAttribPointer(vPosition!!, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer)
            //使能片元属性数组，使之有效
            GLES20.glEnableVertexAttribArray(fPosition!!)
            //使能之后，为片元属性赋值，绑定纹理坐标
            GLES20.glVertexAttribPointer(fPosition!!, 2, GLES20.GL_FLOAT, false, 8, fragmentBuffer)
            //要开始绘制纹理了，激活纹理 0号， 之所以激活 0号，是因为在没设置点的情况下默认是 0号
            GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
            //绑定 textureIds[0] 到已激活的 2D纹理 GL_TEXTURE0上
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[0])
            //获取图片的 bitmap
            val bitmap = BitmapFactory.decodeResource(mContext.resources, R.drawable.nobb)
            //绑定 bitmap 到textureIds[0]纹理
            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0)
            bitmap.recycle() //用完及时回收
            //绘制图形
            GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4)
            //解绑 2D纹理
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0)
        }
    }
}